/*
- @Author: Wangjun
- @Date: 2021-05-21 14:44:32
  - @LastEditTime: 2025-07-09 18:27:21
  - @LastEditors: wangjun haodreams@163.com

- @Description:
- @FilePath: copy form libs/buffer.go
- hnxr
*/
package easy

import (
	"encoding/binary"
	"errors"
	"fmt"
	"io"
	"math"
	"reflect"
)

// 没有足够的空间
var ErrFull = errors.New("缓冲区空间已满")
var ErrLoopInvalid = errors.New("循环覆盖模式下不支持的操作")
var ErrNotEnoughData = errors.New("缓冲区没有足够的数据")

// 高性能的循环缓存,数据0分配, 默认为小编码
type Buffer struct {
	EndianRead
	buf      []byte //缓冲区
	cap      int    //最大容量
	readPos  int    //读开始位置
	writePos int    //写开始位置
}

//Read ...
/*接收指定的字节数, 当没有错误发生时, num = len(data)
* 当有错误发生是num为实际接收的字节数
 */
func ReadFull(conn io.Reader, data []byte) (num int, err error) {
	length := len(data)
	num = 0
	for num < length {
		n, err := conn.Read(data[num:])
		if err != nil {
			return num, err
		}
		num += n
	}
	return
}

// NewBuffer 新建一个缓冲区，且写位置移到数据结尾,如果写移到开头，调用一下Reset()函数
func NewBuffer(data []byte) *Buffer {
	m := new(Buffer)
	m.SetData(data)
	return m
}

// 从reader中读取数据
func NewBufferFromReader(reader io.Reader) *Buffer {
	m := new(Buffer)
	data, err := io.ReadAll(reader)
	if err != nil {
		return nil
	}
	m.SetData(data)
	return m
}

// NewBufferWithSize 新建一个固定大小的缓存
func NewBufferWithSize(size int) *Buffer {
	m := new(Buffer)
	return m.Resize(size)
}

func (m *Buffer) New() *Buffer {
	b := new(Buffer)
	b.endian = m.endian
	return b
}

// buf复位
func (m *Buffer) Reset() *Buffer {
	m.readPos = 0
	m.writePos = 0
	if m.endian == nil {
		m.endian = binary.LittleEndian
	}
	if m.reader == nil {
		m.reader = m
	}
	return m
}

// 获取全部的字节（内部缓冲区）
func (m *Buffer) AllBytes() []byte {
	return m.buf
}

// 获取数组大小
func (m *Buffer) Cap() int {
	return int(m.cap)
}

// 缓冲区可读取字符长度( 可读的大小)
func (m *Buffer) Len() int {
	size := m.writePos - m.readPos
	if size <= 0 {
		if m.writePos > 0 { //自动复位
			m.writePos = 0
			m.writePos = 0
		}
		return 0
	}
	return size
}

// 可写的大小
func (m *Buffer) AvailWrite() int {
	return m.cap - m.Len()
}

func (m *Buffer) Name() string {
	return "buf"
}

// 设置是否大端编码
func (m *Buffer) SetBigEndian(b bool) *Buffer {
	if b {
		m.endian = binary.BigEndian
	} else {
		m.endian = binary.LittleEndian
	}
	return m
}

// 查询指定长度字节的数据
func (m *Buffer) Peek(n int) (data []byte, err error) {
	n = min(n, m.Len())
	data = m.buf[m.readPos : m.readPos+n]
	return
}

// 需要结合SetOffsetEnd使用，获取当前坐标到结束坐标的字节数据
func (m *Buffer) FreeBytes(n int) (data []byte, err error) {
	if n == 0 {
		data = m.buf[m.writePos:m.cap]
		return
	}
	end := n + m.writePos
	if end > m.cap {
		return nil, ErrNotEnoughData
	}

	data = m.buf[m.writePos:end]
	return
}

// 设置结束坐标, 从当前坐标开始偏移offset个字节, 并设置结束坐标为当前坐标+offset
// 配合 Avalibytes使用，复用AvaliBytes的结果
func (m *Buffer) SetEndOffset(offset int) (err error) {
	end := m.writePos + offset
	if end > m.cap {
		return ErrNotEnoughData
	}
	m.writePos = end
	return
}

func (m *Buffer) ReadFrom(r io.Reader) (n int64, err error) {
	data, err := m.FreeBytes(0)
	if err != nil {
		return
	}
	l, err := r.Read(data)
	if err != nil {
		return
	}
	err = m.SetEndOffset(l)
	if err != nil {
		return
	}
	n = int64(l)
	return
}

func (m *Buffer) Byte() byte {
	v := m.buf[m.readPos]
	m.readPos++
	return v
}

// 必须读取指定字节的数据
func (m *Buffer) ReadBytes(n int) (data []byte, err error) {
	if m.Len() < n {
		return nil, ErrNotEnoughData
	}

	data = m.buf[m.readPos : m.readPos+n]
	m.readPos += n
	return
}

// 读取一个字符串
func (m *Buffer) ReadString(b byte) (data string, err error) {
	if m.Len() == 0 {
		return "", io.EOF
	}
	for i := m.readPos; i < m.writePos; i++ {
		if m.buf[i] == b {
			end := i + 1
			data = string(m.buf[m.readPos:end])
			m.readPos = end
			return
		}
	}
	data = string(m.buf[m.readPos:m.writePos])
	m.readPos = m.writePos
	return
}

// 从r中读取n个字节，最好配合TimeoutConn使用
func (m *Buffer) ReadFromReader(n int, r io.Reader) (err error) {
	if n > m.AvailWrite() {
		return ErrFull
	}
	num, err := ReadFull(r, m.buf[m.writePos:m.writePos+n])
	if err != nil {
		return
	}
	m.writePos += num
	return
}

// 实现Read 接口
func (m *Buffer) Read(p []byte) (n int, err error) {
	if m.Len() == 0 {
		return 0, io.EOF
	}

	n = copy(p, m.buf[m.readPos:m.writePos])
	m.readPos += n
	return
}

// 统计字符出现的次数
func (m *Buffer) Count(b byte) int {
	count := 0
	for i := m.readPos; i < m.writePos; i++ {
		if m.buf[i] == b {
			count++
		}
	}
	return count
}

// 实现Write 接口
// 使用前必须保证有足够的剩余空间
func (m *Buffer) Write(p []byte) (n int, err error) {
	n = len(p)
	if n > m.AvailWrite() {
		return 0, ErrFull
	}

	m.writePos += copy(m.buf[m.writePos:], p)
	return
}

// 增加自动设置结束坐标
func (m *Buffer) WriteAt(p []byte, off int64) (n int, err error) {
	if off+int64(len(p)) >= int64(m.cap) {
		err = io.EOF
		return
	}
	n = copy(m.buf[off:], p)
	pos := n + int(off)
	if pos > m.writePos {
		m.writePos = pos
	}
	return
}

// 写入字符串
func (m *Buffer) WriteString(text string) (n int, err error) {
	return m.Write([]byte(text))
}
func (m *Buffer) Printf(format string, a ...any) (n int, err error) {
	return fmt.Fprintf(m, format, a...)
}

// 重新初始化大小
func (m *Buffer) Resize(size int) *Buffer {
	if size <= cap(m.buf) {
		m.cap = size
		m.buf = m.buf[:size]
		m.Reset()
		return m
	}
	m.buf = make([]byte, size)
	m.cap = size
	m.Reset()
	return m
}

// 跳过多少个字节
func (m *Buffer) Skip(n int) (err error) {
	m.readPos += n
	if m.readPos >= m.writePos {
		err = io.EOF
	}
	return
}

func (m *Buffer) Bytes() []byte {
	if m.Len() == 0 {
		return nil
	}
	return m.buf[m.readPos:m.writePos]
}

func (m *Buffer) String() string {
	return string(m.Bytes())
}

// 设置数据缓冲区并对数据进行复位操作,写移到数据尾部，常用于数据解析
func (m *Buffer) SetData(data []byte) *Buffer {
	m.buf = data
	m.cap = len(m.buf)
	m.Reset()
	m.writePos = m.cap
	return m
}

/**
 * @description: 实现ReadAt接口
 * @param {[]byte} p
 * @return {*}
 */
func (m *Buffer) ReadAt(p []byte, off int64) (n int, err error) {
	if off >= int64(m.cap) {
		err = io.EOF
		return
	}
	n = copy(p, m.buf[off:])
	if n+int(off) >= m.cap {
		err = io.EOF
		return
	}
	return
}

/**
 * @description: 实现Seek接口(读操作, 写不支持)
 * @param {[]byte} p
 * @return {*}
 */
func (m *Buffer) Seek(offset int64, whence int) (int64, error) {
	if offset == 0 {
		return int64(m.readPos), nil
	}
	switch whence {
	case io.SeekStart:
		m.readPos = max(int(offset), 0)
		if m.readPos > m.writePos {
			m.readPos = m.writePos
			return 0, io.EOF
		}
	case io.SeekCurrent:
		m.readPos += int(offset)
		if m.readPos < 0 {
			m.readPos = 0
		}
		if m.readPos > m.writePos {
			m.readPos = m.writePos
			return 0, io.EOF
		}
	case io.SeekEnd:
		m.readPos = max(m.cap+int(offset), 0)
		if m.readPos > m.writePos {
			m.readPos = m.writePos
			return 0, io.EOF
		}
	}
	return int64(m.readPos), nil
}

func (m *Buffer) PutInt64(val int64) *Buffer {
	return m.PutUint64(uint64(val))
}

func (m *Buffer) PutUint64(val uint64) *Buffer {
	m.endian.PutUint64(m.buf[m.writePos:], val)
	m.writePos += 8
	return m
}

func (m *Buffer) PutInt32(val int32) *Buffer {
	return m.PutUint32(uint32(val))
}

func (m *Buffer) PutUint32(val uint32) *Buffer {
	m.endian.PutUint32(m.buf[m.writePos:], val)
	m.writePos += 4
	return m
}

func (m *Buffer) PutInt16(val int16) *Buffer {
	return m.PutUint16(uint16(val))
}

func (m *Buffer) PutUint16(val uint16) *Buffer {
	m.endian.PutUint16(m.buf[m.writePos:], val)
	m.writePos += 2
	return m
}
func (m *Buffer) PutFloat32(val float32) *Buffer {
	return m.PutUint32(math.Float32bits(val))
}

func (m *Buffer) PutFloat64(val float64) *Buffer {
	return m.PutUint64(math.Float64bits(val))
}

func (m *Buffer) WriteByte(b byte) (err error) {
	if m.writePos >= m.cap {
		return io.EOF
	}
	m.buf[m.writePos] = b
	m.writePos++
	return

}

func (m *Buffer) PutByte(b byte) *Buffer {
	m.WriteByte(b)
	return m
}

// 写入一批数据
func (m *Buffer) WriteAny(p ...any) (n int) {
	for i, v := range p {
		switch f := v.(type) {
		case bool:
			if f {
				m.PutByte(1)
			} else {
				m.PutByte(0)
			}
			n++
		case float32:
			n += 4
			m.PutFloat32(f)
		case float64:
			n += 8
			m.PutFloat64(f)
		case int8:
			m.PutByte(byte(f))
			n++
		case int16:
			m.PutInt16(f)
			n += 2
		case int32:
			m.PutInt32(f)
			n += 4
		case int64:
			m.PutInt64(f)
			n += 8
		case uint8:
			m.PutByte(f)
			n++
		case uint16:
			m.PutUint16(f)
			n += 2
		case uint32:
			m.PutUint32(f)
			n += 4
		case uint64:
			m.PutUint64(f)
			n += 8
		case []byte:
			num, _ := m.Write(f)
			n += num
		case string:
			num, _ := m.Write([]byte(f))
			n += num
		default:
			t := reflect.TypeOf(f)
			panic(fmt.Sprintf("第 %d 个参数 [%s] 格式不支持", i+1, t.Kind().String()))
		}
	}
	return
}

// CRC16 计算 data CRC码值
func (m *Buffer) CRC16(pos ...int) (crc uint16, err error) {
	begin := 0
	end := m.Len()
	if len(pos) > 0 {
		begin = pos[0]
	}
	if len(pos) > 1 {
		end = pos[2]
	}

	crc = CRC16(m.buf[begin:end])
	return crc, err
}

// 计算校验和
func (m *Buffer) CheckSum(pos ...int) (sum byte, err error) {
	begin := 0
	end := m.Len()
	if len(pos) > 0 {
		begin = pos[0]
	}
	if len(pos) > 1 {
		end = pos[2]
	}

	sum = CheckSum(m.buf[begin:end])
	return
}

// CRC16 计算 data CRC码值
func CRC16(data []byte) (crc uint16) {
	l := len(data)
	crc = 0xffff
	for i := 0; i < l; i++ {
		crc = crc ^ uint16(data[i])
		for j := 0; j < 8; j++ {
			if (crc & 1) != 0 {
				crc = (crc >> 1) ^ 0xa001
			} else {
				crc = crc >> 1
			}
		}
	}
	return
}

// 计算校验和
func CheckSum(data []byte) byte {
	sum := byte(0)
	for _, v := range data {
		sum += v
	}
	return sum
}
